/**
 * 
 */

var renderer;
var canvas;
var pointMode = false;
function initThree() {
	$('#canvas-frame').width(canvas_width);
	$('#canvas-frame').height(canvas_height);
	width = canvas_width;
	height = canvas_height;
	//width = document.getElementById('canvas-frame').clientWidth;
	//height = document.getElementById('canvas-frame').clientHeight;
	renderer = new THREE.WebGLRenderer({
		antialias : true
	});
	renderer.setSize(width, height);
	document.getElementById('canvas-frame').appendChild(renderer.domElement);
	renderer.setClearColorHex(0x191824, 1.0);
}

var camera;
function initCamera() {
	camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
	camera.position.x = canvas_rad;
	camera.position.y = 0;
	camera.position.z = 0;
	camera.up.x = 0;
	camera.up.y = 0;
	camera.up.z = 1;
	camera.lookAt({
		x : 0,
		y : 0,
		z : -15
	});
}
var scene;
function initScene() {
	scene = new THREE.Scene();
}
var light, light2;
function initLight() {
	light = new THREE.DirectionalLight(0xFFFFFF, 1.0, 0);
	light.position.set(600, 0, 0);
	scene.add(light);

	// light2 = new THREE.AmbientLight(0xFFFFFF);
	// scene.add(light2);
}

var canvas_height;
var canvas_width;
function updateHeightAndWidth(){
    //获取窗口宽度
	var winWidth, winHeight;
    if (window.innerWidth)
          winWidth = window.innerWidth;
    else if ((document.body) && (document.body.clientWidth))
          winWidth = document.body.clientWidth;
    //获取窗口高度
    if (window.innerHeight)
          winHeight = window.innerHeight;
    else if ((document.body) && (document.body.clientHeight))
          winHeight = document.body.clientHeight;
  
    //通过深入Document内部对body进行检测，获取窗口大小
    if (document.documentElement  && document.documentElement.clientHeight &&
                                         document.documentElement.clientWidth)
    {
        winHeight = document.documentElement.clientHeight;
        winWidth = document.documentElement.clientWidth;
    }
	canvas_height = winHeight;
	canvas_width = winWidth;
	canvas_rad = Math.min(canvas_height,canvas_width);
	radius = 170 / 600 * canvas_rad;
}
var canvas_rad;
// set the radius according to canvas size
var radius;

var plane = Array();
var line = Array();
var m1;
var selBall;
var texture_point;
var texture_select;
var circle;
var user_list;
function initObject() {
	// add the selection ball
	var r = 0.6 * radius;
	selBall = new THREE.Mesh(new THREE.SphereGeometry(r, r, r),
			new THREE.MeshLambertMaterial({
				color : 0xFFFFFF,
				opacity : 0.2,
				depthTest : false,
				blending : THREE.AdditiveBlending,
				transparent : true
			}));
	scene.add(selBall);
	selBall.visible = false;
	selBall.position.set(radius * 0.8, 0, 0);
	var texture_circle = new THREE.ImageUtils.loadTexture('circle.jpg');
	circle = new THREE.Mesh(new THREE.PlaneGeometry(327, 327, 1, 1),
			new THREE.MeshLambertMaterial({
				map : texture_circle,
				blending : THREE.AdditiveBlending,
				depthTest : false,
				transparent : true,
				vertexColors : true
			// allows 1 color per particle
			}));
	scene.add(circle);
	circle.position.set(radius * 0.8, 0, 0);
	circle.scale.set(r / 327, r / 327, r / 327);
	circle.rotation.set(0, 0, -Math.PI / 2);
	
	// calculate the color
	var texture1 = texture_point = new THREE.ImageUtils.loadTexture('point.jpg');
	texture_select = new THREE.ImageUtils.loadTexture('select.jpg');
	var square_size = 20 / 600 * canvas_rad;
	for ( var i = 0; i < itemNum; i++) {
		var color = getColorByDistance(user_list[i].distance);
		if (pointMode) {
			plane[i] = new THREE.Mesh(new THREE.PlaneGeometry(square_size, square_size, 1, 1),
					new THREE.MeshLambertMaterial({
						map : texture1,
						blending : THREE.AdditiveBlending,
						depthTest : false,
						transparent : true,
						vertexColors : true,
						color: color
					// allows 1 color per particle
					}));
		} else {
			var tmp = getCanvasTexture(user_list[i].username);
			var texture = new THREE.Texture(tmp);
			texture.setSelected = function(selected, tmp) {
				tmp.selected = selected;
				if (selected) {
					drawLine(tmp);
				} else {
					clearLine(tmp);
				}
			};
			texture.needsUpdate = true;
			var ratio = canvas_rad / 600 / 3;
			plane[i] = new THREE.Mesh(new THREE.PlaneGeometry(tmp.width * ratio,
					tmp.height * ratio, 1, 1), new THREE.MeshBasicMaterial({
				map : texture,
				blending : THREE.AdditiveBlending,
				depthTest : false,
				transparent : true,
				vertexColors : true,
				color: color
			// allows 1 color per particle
			}));
		}

		scene.add(plane[i]);
		var position = getPositionByDistance(user_list[i].distance);
		var alpha = plane[i].alpha = position.alpha;
		var beta = plane[i].beta = position.beta;
		//var alpha = plane[i].alpha = Math.random() * 2 * Math.PI;
		//var beta = plane[i].beta = (Math.random() - 0.5) * Math.PI;
		plane[i].position.set(radius * Math.sin(alpha) * Math.cos(beta), radius
				* Math.cos(alpha) * Math.cos(beta), radius * Math.sin(beta));
		plane[i].material_old = plane[i].material;
		plane[i].rotation.set(Math.PI, 0, -Math.PI / 2);

		var tmp = new THREE.Geometry();
		tmp.vertices.push(new THREE.Vector3(0, 0, 0));
		tmp.vertices.push(plane[i].position);
		m1 = new THREE.LineBasicMaterial({
			color : 0xFFFFFF,
			opacity : 1,
			blending : THREE.NormalBlending,
			transparent : true
		});
		line[i] = new THREE.Line(tmp, m1);

		scene.add(line[i]);
	}
}
function getColorByDistance(distances){
	var colors = [{r:0xFF,g:0x8c,b:0xb0},
	              {r:0xad,g:0xFF,b:0x70},
	              {r:0x64,g:0xc6,b:0xFF}];
	var color = new Object();
	var weight = 0;
	var num = distances.length - 1;
	color.r = color.g = color.b = 0;
	for (i = 1; i <= num; i++){
		var dis;
		if (distances[i] == 0)
			dis = 2;
		else
			dis = 1/(distances[i]);
		weight += dis;
		color.r += dis * colors[i - 1].r;
		color.g += dis * colors[i - 1].g;
		color.b += dis * colors[i - 1].b;
	}
	color = ((color.r/weight)<<16)
				|((color.g/weight)<<8)|((color.b/weight));
	return color;
}
// user one distance and 3 additional distance to calculate
// the position of the point
function getPositionByDistance(distances){
	var a = normalizeDistance(distances[0]) * Math.PI;
	var num = distances.length - 1;
	var x = 0, y = 0;
	var delta = Math.PI * 2 / num, sumDelta = 0;
	for (i = 1; i <= num; i++){
		var dis;
		if (distances[i] == 0)
			dis = 2;
		else
			dis = 1/distances[i];
		x += dis * Math.cos(sumDelta);
		y += dis * Math.sin(sumDelta);
		sumDelta += delta;
	}
	var b = Math.atan(y/x);
	if (b < 0)
		if (x > 0)
			b += Math.PI * 2;
		else
			b += Math.PI;
	else if (x < 0)
		b += Math.PI;
	
	y = Math.cos(a);
	x = Math.sin(a) * Math.cos(b);
	z = Math.sin(a) * Math.sin(b);
	var position = new Object();
	position.beta = Math.asin(z);
	var b = Math.atan(y/x);
	if (b < 0)
		if (x > 0)
			b += Math.PI * 2;
		else
			b += Math.PI;
	else if (x < 0)
		b += Math.PI;
	position.alpha = b;
	return position;
}
function normalizeDistance(distance){
	if (distance < 0)
		return 0;
	//if (distance < 0.9)
	//	return (1/(distance+1));
	//return 1 - (1/(distance+9.1));
	if (distance < 0.1)
		return distance * 0.25;
	if (distance < 0.3)
		return 0.025 + ((distance-0.1) / 0.2 * 0.475);
	return 1-(0.5/(0.5+distance));
}

function drawLine(canvas) {
	var height = canvas.height, width = canvas.width;
	var context = canvas.getContext('2d');
	context.beginPath();
	context.moveTo(width / 4, height - 1);
	context.lineTo(width / 4 * 3, height - 1);
	context.closePath();
	context.strokeStyle = "white" ;
	context.stroke();
}
function clearLine(canvas) {
	var height = canvas.height, width = canvas.width;
	var context = canvas.getContext('2d');
	context.clearRect(0, height - 2, width, 2);
}


function getCanvasTexture(str, color) {
	$("body").append(
			"<canvas id ='" + str + "' style='display:none;'></canvas>");
	var canvas = document.getElementById(str);
	canvas.width = str.length * 36;
	canvas.height = 48;
	var context = canvas.getContext('2d');
	context.fillStyle = 'black';
	context.fillRect(0, 0, canvas.width, canvas.height);
	context.font = '36px Microsoft YaHei';
	context.fillStyle = "white";
	context.textAlign = "center";
	context.textBaseline = "middle";
	context.fillText(str, canvas.width / 2, canvas.height / 2);

	context.restore();

	return canvas;
}

var cube_x = 100;
var r = 0;
function normalizeAB() {
	var a = dAlpha, b = dBeta;
	if (Math.cos(b) < 0) {
		b = Math.PI - b;
		a = Math.PI + a;
	}
	while (a < -Math.PI) {
		a += 2 * Math.PI;
	}
	while (a > Math.PI) {
		a -= 2 * Math.PI;
	}
	while (b < -Math.PI) {
		b += 2 * Math.PI;
	}
	while (b > Math.PI) {
		b -= 2 * Math.PI;
	}
	return [ a, b ];
}

function colorToVector(color) {
	return new THREE.Vector3(color >> 16, (color >> 8) & 0xFF, color & 0xFF);
}

function distance(a, b) {
	var d1 = (a >> 16) - (b >> 16), d2 = ((a >> 8) & 0xFF) - ((b >> 8) & 0xFF), d3 = (a & 0xFF)
			- (b & 0xFF);
	return d1 * d1 + d2 * d2 + d3 * d3;
}

var doPick = false;
//var itemNum = 300;
var pickColors = Array();
var selCount = 0;
var lastTime = 0;

function loop() {
	window.requestAnimationFrame(loop);

	var elapsed = 1;
	var timeNow = new Date().getTime();
	if (lastTime != 0) {
		elapsed = timeNow - lastTime;
	}
	lastTime = timeNow;

	if (goToCenter) {
		dAlpha *= 0.8;
		dBeta *= 0.8;
		if (dAlpha < 0.01 && dBeta < 0.01 && dAlpha > -0.01 && dBeta > -0.01) {
			dAlpha = dBeta = 0;
			goToCenter = false;
		}
		drawUDControl();
		drawLRControl();
	}

	// handle picking
	//enable pick at all times
	doPick = true;
	if (doPick) {
		selBall.visible = false;
		doPick = false;
		// generate pickColors and color all the particals
		for ( var i = 0; i < itemNum; i++) {
			var alpha = plane[i].alpha + dAlpha;
			var beta = plane[i].beta + dBeta;
			plane[i].position.set(radius * Math.sin(alpha) * Math.cos(beta),
					radius * Math.cos(alpha) * Math.cos(beta), Math.sin(alpha)
							/ Math.abs(Math.sin(alpha)) * radius
							* Math.sin(beta));

			var x = plane[i].position.x;
			if (x > 0) {
				plane[i].visible = true;
				line[i].visible = true;
				var pickcolor;
				if (!pickColors[i])
					pickColors[i] = Math.floor(Math.random() * 0xFFFFFF);
				plane[i].material = new THREE.MeshBasicMaterial({
					color : pickColors[i]
				});
				var x = plane[i].position.x, s = (x + 40) / (radius + 40) * 0.5
						+ 0.2;
				plane[i].scale.set(s, s, s);
			} else {
				plane[i].visible = false;
				line[i].visible = false;
			}
		}

		renderer.clear();
		renderer.render(scene, camera);
		// get the color for the pixel that the mouse is pointing at
		var data; // 0, 0, w, h
		data = new Uint8Array(4); // w * h * 4
		var gl = renderer.context;
		gl.readPixels(pickX, gl.canvas.height - pickY, 1, 1, gl.RGBA,
				gl.UNSIGNED_BYTE, data);
		var pickedColor = (data[0] << 16) + (data[1] << 8) + data[2];

		for ( var i = 0; i < itemNum; i++) {
			if (pickColors[i] && distance(pickedColor, pickColors[i]) <= 10) {
				$("#tags").css("top", pickY + 5);
				$("#tags").css("left", pickX + 5);
				if (pointMode){
					$("#tags").html('<h1>'+user_list[i].username+"</h1>"+user_list[i].keywords);
				}else{
					$("#tags").text(user_list[i].keywords);
				}
				$("#tags").show("fast");
				// $("#tags").css("display","inherit");
				// document.getElementById("debug").textContent = i+"";
			}
		}
	}
	var selCountO = selCount;
	selCount = 0;
	for ( var i = 0; i < itemNum; i++) {
		var alpha = plane[i].alpha + dAlpha;
		var beta = plane[i].beta + dBeta;
		plane[i].position.set(radius * Math.sin(alpha) * Math.cos(beta), radius
				* Math.cos(alpha) * Math.cos(beta), Math.sin(alpha)
				/ Math.abs(Math.sin(alpha)) * radius * Math.sin(beta));

		var x = plane[i].position.x;
		if (x > 0) {
			var s = (x + 40) / (radius + 40);
			m1 = line[i].material;
			scene.remove(line[i]);
			var tmp = new THREE.Geometry();
			tmp.vertices.push(new THREE.Vector3(0, 0, 0));
			tmp.vertices.push(plane[i].position);
			line[i] = new THREE.Line(tmp, m1);
			line[i].position.x = 0;
			line[i].position.y = 0;
			line[i].position.z = 0;

			scene.add(line[i]);

			line[i].visible = true;
			line[i].material.opacity = (s > 0.4) ? s - 0.4 : 0;

			plane[i].scale.set(s, s, s);
			plane[i].visible = true;
			plane[i].material = plane[i].material_old;
			if (pointMode) {
				if (isSelected(alpha, beta)) {
					plane[i].material.map = texture_select;
					selCount++;
				} else {
					plane[i].material.map = texture_point;
				}
			} else {
				if (isSelected(alpha, beta)) {
					if (!plane[i].material.map.image.selected) {
						plane[i].material.map.setSelected(true,
								plane[i].material.map.image);
						plane[i].material.map.needsUpdate = true;
					}
					selCount++;
				} else if (plane[i].material.map.image.selected) {
					plane[i].material.map.setSelected(false,
							plane[i].material.map.image);
					plane[i].material.map.needsUpdate = true;
				}
			}
			plane[i].material.opacity = Math.sqrt(s)
					* (0.9 + 0.1 * Math.sin(timeNow / 400 + alpha * 4 + beta
							* 5));
			;

		} else {
			plane[i].visible = false;
			line[i].visible = false;
		}
	}

	if (selRad > 0) {
		circle.visible = true;
		selBall.visible = true;
		circle.rotation.x -= (5 * elapsed) / 1000.0;
		if (selBall.rad == undefined || selRad != selBall.rad) {
			var r = Math.sin(selRad) * radius;
			scene.remove(selBall);
			selBall = new THREE.Mesh(new THREE.SphereGeometry(r, r, r),
					new THREE.MeshLambertMaterial({
						color : 0xFFFFFF,
						depthTest : false,
						blending : THREE.AdditiveBlending,
						transparent : true
					}));
			selBall.rad = selRad;
			selBall.position.set(radius * Math.cos(selRad), 0, 0);
			scene.add(selBall);
			circle.scale.set(r / 145, r / 145, r / 145);
			circle.position.set(radius * Math.cos(selRad), 0, 0);
		}
		selBall.material.opacity = 0.2 * (0.9 + 0.1 * Math.sin(timeNow / 200));
	} else {
		selBall.visible = false;
		circle.visible = false;
	}
	// if number of selection has changes, redraw
	if (selCount != selCountO) {
		drawSelectionControl();
	}

	renderer.clear();
	renderer.render(scene, camera);
}

// use ajax to get view information
function getViewInfo(){
	$.ajax({url:'ViewInfoServlet?type=view', type:"get",
		dataType:"json",
		//data:({type:"view"}),
		timeout:30000,
		success:gotViewJson});
}

// get and pre-process data
function initData(){
	getViewInfo();
}
var user_info_list = new Object();
function gotViewJson(dataObj){
	itemNum = dataObj.length;
	user_list = dataObj;
	var users = new Array();
	
	$.ajax({url:'ViewInfoServlet?type=user', type:"get",
		//data:users.toJSONString(),
		dataType:"json",
		//data:({type:"user"}),
		timeout:30000,
		success:gotUserJson});
}

function gotUserJson(dataObj){
	var len = dataObj.length;
	var i;
	for (i = 0; i < len; i++){
		var uid = dataObj[i].uid;
		if (!user_info_list[uid]){
			user_info_list[uid] = dataObj[i];
		}
	}
	threeStart();
}

// decide if point alpha beta is within selection
function isSelected(alpha, beta) {
	var b = (Math.sin(Math.PI * 0.5 - alpha)), a = Math.sin(beta), c = Math
			.sin(selRad * 0.5);
	return (a * a + b * b) / 4 < (c * c);
}

var context;
function initCanvas() {
	canvas = document.getElementById("canvas2D");
	$("#canvas2D").attr("height",canvas_height);
	$("#canvas2D").attr("width",canvas_width);
	
	context = canvas.getContext("2d");

	// draw center control
	var centerX = canvas_width - 60, centerY = 60, radius = 17;
	context.arc(centerX, centerY, radius, 0, Math.PI * 2, true);
	context.lineWidth = 1;
	context.strokeStyle = "white";
	context.stroke();

	drawSmallCenter();

	// draw up-down-ward control
	drawUDControl();

	// drwa left-right control
	drawLRControl();

	// draw selection control
	drawSelectionControl();
}

var selRad = 0;
var arrowShape = [ [ -1, 1 ], [ -1, -0.5 ], [ -0.5, -0.5 ], [ 1, -1 ],
		[ 1, 0.5 ], [ 0.5, 0.5 ] ];
function drawSelectionControl() {
	context.clearRect(34, canvas_height - 141, 117, 117);
	context.beginPath();
	context.moveTo(35, canvas_height - 140);
	context.lineTo(35, canvas_height - 25);
	context.lineTo(150, canvas_height - 25);
	context.lineWidth = 1;
	context.strokeStyle = "white";
	context.stroke();

	var radius = selRad * 85 * 2 / Math.PI + 30;
	context.beginPath();
	context.moveTo(35, canvas_height - 25);
	context.arc(35, canvas_height - 25, radius, 1.5 * Math.PI, 0, false);
	context.lineTo(35, canvas_height - 25);
	context.closePath();
	context.fillStyle = "#2b2c41";
	context.fill();

	context.beginPath();
	context.arc(35, canvas_height - 25, radius, 1.5 * Math.PI, 0, false);
	context.lineWidth = 1;
	context.strokeStyle = "white";
	context.stroke();

	// drawArrow
	var startX = 35 + radius * 0.7;
	var startY = canvas_height - 25 - radius * 0.7;
	var size = 6;
	var as = arrowShape;
	context.beginPath();
	context.moveTo(startX + as[0][0] * size, startY + as[0][1] * size);
	context.lineTo(startX + as[1][0] * size, startY + as[1][1] * size);
	context.arc(startX + as[2][0] * size, startY + as[2][1] * size, size * 0.5,
			Math.PI, 1.5 * Math.PI, true);
	context.lineTo(startX + as[3][0] * size, startY + as[3][1] * size);
	context.lineTo(startX + as[4][0] * size, startY + as[4][1] * size);
	context.arc(startX + as[5][0] * size, startY + as[5][1] * size, size * 0.5,
			0, 0.5 * Math.PI, true);
	context.closePath();
	context.fillStyle = "white";
	context.fill();

	// draw text
	context.font = "12px Simsun";
	context.fillStyle = "#FFFFFF";
	context.fillText(selCount + "人", 37, canvas_height - 28);
}

var startY;
function drawUDControl() {
	var mid_y = canvas_height / 2;
	context.clearRect(35 - 4, mid_y - 150, 30, 280);

	var x = normalizeAB()[1];
	context.beginPath();
	context.moveTo(35, mid_y - 135);
	context.lineTo(35, mid_y + 115);
	context.closePath();
	context.lineWidth = 1;
	context.strokeStyle = "white";
	context.stroke();

	startY = mid_y - 135 + 250 * (x / Math.PI + 0.5);
	context.beginPath();
	context.moveTo(35 + 10, startY);
	context.lineTo(35 + 16, startY - 6);
	context.lineTo(35 + 24, startY - 6);
	context.lineTo(35 + 24, startY + 6);
	context.lineTo(35 + 16, startY + 6);
	context.closePath();
	context.fillStyle = "white";
	context.fill();
	context.beginPath();
	context.moveTo(35, startY - 4);
	context.lineTo(35 - 4, startY);
	context.lineTo(35, startY + 4);
	context.lineTo(35 + 4, startY);
	context.closePath();
	context.fillStyle = "white";
	context.fill();
}

var startX;
function drawLRControl() {
	var mid_x = canvas_width / 2,
		base_y = canvas_height - 25;
	context.clearRect(mid_x - 140, base_y - 25, 280, 30);

	var x = normalizeAB()[0];
	context.beginPath();
	context.moveTo(mid_x - 125, base_y);
	context.lineTo(mid_x + 125, base_y);
	context.closePath();
	context.lineWidth = 1;
	context.strokeStyle = "white";
	context.stroke();

	startX = mid_x - 125 + 250 * (x / Math.PI + 1) / 2;
	context.beginPath();
	context.moveTo(startX, base_y - 10);
	context.lineTo(startX - 6, base_y - 16);
	context.lineTo(startX - 6, base_y - 24);
	context.lineTo(startX + 6, base_y - 24);
	context.lineTo(startX + 6, base_y - 16);
	context.closePath();
	context.fillStyle = "white";
	context.fill();
	context.beginPath();
	context.moveTo(startX - 4, base_y);
	context.lineTo(startX, base_y - 4);
	context.lineTo(startX + 4, base_y);
	context.lineTo(startX, base_y + 4);
	context.closePath();
	context.fillStyle = "white";
	context.fill();
}

function initComponents() {
	$("#tags").mouseout(function() {
		$("#tags").hide("fast");
	});
}

function threeStart() {
	updateHeightAndWidth();
	initComponents();
	initCanvas();
	initThree();
	initCamera();
	initScene();
	initLight();
	initObject();
	renderer.clear();
	renderer.render(scene, camera);
	loop();
}

var dAlpha = 0, dBeta = 0;
var down = false;
var sx = 0, sy = 0;
var pickX = 0, pickY = 0;
var centerFlag = false;
var goToCenter = false;
var moveY = false;
var moveX = false;
var moveSel = false;
var lastMouseDown;
var tagDisplayTime = 60;
window.onmousedown = function(ev) { // マウスダウン
	if (ev.target == canvas) {
		down = true;
		sx = ev.clientX;
		sy = ev.clientY;
		lastMouseDown = new Date().getTime();
		if (sx < 35 + 28 && sx > 35 && sy > startY - 10 && sy < startY + 10) {
			moveY = true;
		}
		base_y = canvas_height - 25;
		if (sy > base_y - 28 && sy < base_y && sx > startX - 10 && sx < startX + 10) {
			moveX = true;
		}

		var radius = selRad / Math.PI * 2 * 85 + 30;
		selX = 35 + radius * 0.7;
		selY = base_y - radius * 0.7;
		if (sy > selY - 10 && sy < selY + 10 && sx > selX - 10
				&& sx < selX + 10) {
			moveSel = true;
		}
	}
};
window.onmouseup = function(ev) { // マウスアップ
	down = false;
	moveY = false;
	moveX = false;
	moveSel = false;
	if (centerFlag) {
		goToCenter = true;
		var ab = normalizeAB();
		dAlpha = ab[0];
		dBeta = ab[1];
	}
	//if (new Date().getTime() - lastMouseDown <= 500) {
	//	if (ev.target == canvas) {
			
	//		pickX = ev.clientX;
	//		pickY = ev.clientY;
	//		doPick = true;
	//	}
	//}
};
window.onmousemove = function(ev) { // マウスムーブ
	//enable pick at all times
	var cvx = $('#canvas-frame').offset().top; 
	var cvy = $('#canvas-frame').offset().left;
	pickX = ev.clientX - cvx;
	pickY = ev.clientY - cvy;
	
	var speed = 0.005;
	var centerX = canvas_width - 60, centerY = 60;
	var mid_x = canvas_width / 2, mid_y = canvas_height / 2;
	if (down) {
		if (ev.target == canvas) {
			$("#tags").hide("fast");
			if (moveY) {
				var cy = ev.clientY;
				if (cy < (mid_y - 135))
					cy = mid_y - 135;
				if (cy > (mid_y + 115))
					cy = mid_y + 115;
				var ab = normalizeAB();
				dAlpha = ab[0];
				dBeta = (cy - mid_y + 10) / 250 * Math.PI;
				drawUDControl();
			} else if (moveX) {
				var cx = ev.clientX;
				if (cx < (mid_x - 125))
					cx = mid_x - 125;
				if (cx > (mid_x + 125))
					cx = mid_x + 125;
				var ab = normalizeAB();
				dBeta = ab[1];
				dAlpha = (cx - mid_x) / 250 * Math.PI * 2;
				drawLRControl();
			} else if (moveSel) {
				var cx = ev.clientX, cy = ev.clientY;
				var base_y = canvas_height - 25;
				var cr = Math.sqrt((cx - 35) * (cx - 35) + (cy - base_y)
						* (cy - base_y)) - 30;
				if (cr < 0) {
					selRad = 0;
				} else if (cr <= 85) {
					selRad = Math.PI * 0.5 * cr / 85;
				} else {
					selRad = Math.PI * 0.5;
				}
				drawSelectionControl();
			} else {
				var dx = (ev.clientX - sx);
				var dy = (ev.clientY - sy);
				dAlpha -= dx * speed;
				dBeta -= dy * speed;
				sx = ev.clientX;
				sy = ev.clientY;
				drawUDControl();
				drawLRControl();
			}
		}
	} else if (ev.clientX > centerX - 10 && ev.clientX < centerX + 10
			&& ev.clientY > centerY - 10 && ev.clientY < centerY + 10) {
		if (!centerFlag) {
			drawBigCenter();
			centerFlag = true;
		}
	} else if (centerFlag) {
		clearCenter();
		drawSmallCenter();
		centerFlag = false;
	}
};
function drawSmallCenter() {
	var centerX = canvas_width - 60, centerY = 60;
	context.beginPath();
	context.arc(centerX, centerY, 3, 0, Math.PI * 2, true);
	context.closePath();
	context.fillStyle = "#e84040";
	context.fill();
}
function drawBigCenter() {
	var centerX = canvas_width - 60, centerY = 60;
	context.beginPath();
	context.arc(centerX, centerY, 4, 0, Math.PI * 2, true);
	context.closePath();
	context.fillStyle = "#e88787";
	context.fill();
}
function clearCenter() {
	var centerX = canvas_width - 60, centerY = 60;
	context.clearRect(centerX - 4, centerY - 4, 8, 8);
}